//
// Created by amon.huang on 2021/7/28.
//

#include "MediaBase.h"
#include "MusicConstDefine.h"

void MediaBase::analysisStream(ThreadMode threadMode, AVFormatContext *pFormatContext) {
    analysisStreamCommon(threadMode, pFormatContext);
    analysisStreamInner(threadMode, pFormatContext);
}

void MediaBase::release() {
    if (pPackQueue) {
        pPackQueue->clear();
        delete pPackQueue;
        pPackQueue = nullptr;
    }

    if (pCodecContext) {
        avcodec_close(pCodecContext);
        avcodec_free_context(&pCodecContext);
        pCodecContext = nullptr;
    }
}

MediaBase::MediaBase(int streamIndex, JNICall *pJNICall, PlayerStatus *pPlayerStatus) :
        streamIndex(streamIndex),
        pJniCall(pJNICall),
        pPlayerStatus(pPlayerStatus) {
    pPackQueue = new PacketQueue();
}

MediaBase::~MediaBase() {
    release();
}

void MediaBase::callPlayJniError(ThreadMode threadMode, int code, char *msg) {
    release();
    pJniCall->callPlayError(threadMode, code, msg);
}

void MediaBase::analysisStreamCommon(ThreadMode threadMode, AVFormatContext *pFormatContext) {
    AVCodecParameters *pCodecParameters = pFormatContext->streams[streamIndex]->codecpar;
    AVCodec *avCodec = avcodec_find_decoder(pCodecParameters->codec_id);
    if (!avCodec) {
        LOGE("codec find audio decoder error");
        callPlayJniError(threadMode, -1, "codec find audio decoder error");
        return;
    }

    pCodecContext = avcodec_alloc_context3(avCodec);
    int parametersToContext = avcodec_parameters_to_context(pCodecContext, pCodecParameters);
    if (parametersToContext < 0) {
        LOGE("codec parameters to context error:%s", av_err2str(parametersToContext));
        callPlayJniError(threadMode, parametersToContext, av_err2str(parametersToContext));
        return;
    }
    int codecOpenRes = avcodec_open2(pCodecContext, avCodec, nullptr);
    if (codecOpenRes != 0) {
        LOGE("codec open res error:%s", av_err2str(codecOpenRes));
        callPlayJniError(threadMode, codecOpenRes, av_err2str(codecOpenRes));
        return;
    }

    duration = pFormatContext->duration;
    timeBase = pFormatContext->streams[streamIndex]->time_base;
}

